package hr.ctg.domain.action.objekt;

import hr.ctg.domain.model.Adresa;
import hr.ctg.domain.model.Cijena;
import hr.ctg.domain.model.EmailAdresa;
import hr.ctg.domain.model.Korisnik;
import hr.ctg.domain.model.Objekt;
import hr.ctg.domain.model.Osobina;
import hr.ctg.domain.model.Posjet;
import hr.ctg.domain.model.Rola;
import hr.ctg.domain.model.Telefon;
import hr.ctg.domain.model.TipOsobine;
import hr.ctg.service.dao.DojamPosjetiteljaDAO;
import hr.ctg.service.dao.KorisnikDAO;
import hr.ctg.service.dao.MjestoDAO;
import hr.ctg.service.dao.ObjektDAO;
import hr.ctg.service.dao.OsobinaDAO;
import hr.ctg.service.dao.OtokDAO;
import hr.ctg.service.dao.PosjetDAO;
import hr.ctg.service.dao.TipOsobineDAO;

import java.sql.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.faces.context.FacesContext;

import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.security.Restrict;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Identity;
import org.joda.time.DateTime;

@Name("objektDetailsAction")
public class ObjektDetailsAction {

	@Logger
	Log log;

	@In
	FacesContext facesContext;

	@RequestParameter
	Integer idObjekta;

	@In
	ObjektDAO objektDAO;
	@In
	PosjetDAO posjetDAO;
	@In
	MjestoDAO mjestoDAO;
	@In
	OtokDAO otokDAO;
	@In
	SearchParameters searchParameters;
	@In
	DojamPosjetiteljaDAO dojamPosjetiteljaDAO;
	@In
	TipOsobineDAO tipOsobineDAO;
	@In
	private OsobinaDAO osobinaDAO;
	@In
	KorisnikDAO korisnikDAO;
	@In
	Identity identity;

	@In(required = false)
	Korisnik korisnik;

	// @Out(required = false)
	// DojamPosjetitelja dojamPosjetitelja;
	@Out(required = false)
	Objekt objektDetails;

	@DataModel
	Set<Adresa> adrese;
	@DataModel
	Set<EmailAdresa> emailAdrese;
	@DataModel
	Set<Telefon> telefoni;
	@DataModel
	Set<Osobina> osobine;
	@DataModel
	Set<Cijena> cijene;

	private final Map<Integer, List<Osobina>> osobineCache = new HashMap<Integer, List<Osobina>>();

	@Factory("objektDetails")
	public void getObjekt() {
		objektDetails = objektDAO.findByIdFAEATCOMTOOO(idObjekta);
		adrese = objektDetails.getAdresas();
		emailAdrese = objektDetails.getEmailAdresas();
		telefoni = objektDetails.getTelefons();
		cijene = objektDetails.getCijenas();
		osobine = objektDetails.getOsobinas();

		Object[] counts = objektDAO.findOBDBSByIdObjekta(objektDetails);

		objektDetails.setOcjena((Double) counts[0]);
		objektDetails.setBrojDojmova(Integer.valueOf(((Long) counts[1])
				.intValue()));
		objektDetails.setBrojSlika(Integer.valueOf(((Long) counts[2])
				.intValue()));
		objektDetails.setBrojPosjeta(Integer.valueOf(((Long) counts[3])
				.intValue()));

		searchParameters.setNazivMjesta(objektDetails.getMjesto().getNaziv());
		searchParameters.setTipObjekta(objektDetails.getTipObjekta());
	}

	@Factory("tipoviOsobinaByObjekt")
	public List<TipOsobine> getTipoviOsobina() {
		return tipOsobineDAO.findByIdObjekta(idObjekta);
	}

	public List<Osobina> getOsobine(final Integer idTipaosobine) {
		List<Osobina> osobine;
		if ((osobine = osobineCache.get(idTipaosobine)) == null) {
			osobine = osobinaDAO.findByIdTipaOsobineIdObjekta(idTipaosobine,
					idObjekta);
			osobineCache.put(idTipaosobine, osobine);
		}
		return osobine;
	}

	@Transactional
	public void registerObjektVisit() {
		if (idObjekta != null
				&& !identity.hasRole(Rola.Role.ADMIN.toString())
				&& (facesContext.getExternalContext().getSessionMap().get(
						"posjetObjekta" + idObjekta) == null || !((Boolean) facesContext
						.getExternalContext().getSessionMap().get(
								"posjetObjekta" + idObjekta)).booleanValue())) {
			final Objekt objekt = objektDAO.find(idObjekta);
			final java.util.Date currDate = new DateTime().toDateMidnight()
					.toDate();
			Posjet po = posjetDAO.findByObjektDatumPosjete(idObjekta, currDate);
			if (po == null) {
				po = new Posjet();
				po.setObjekt(objekt);
				po.setDatumPosjete(new Date(currDate.getTime()));
			}

			po.setBrojPosjeta(po.getBrojPosjeta() + 1);
			posjetDAO.merge(po);

			facesContext.getExternalContext().getSessionMap().put(
					"posjetObjekta" + idObjekta, Boolean.valueOf(true));

			Posjet pm = posjetDAO.findByMjestoDatumPosjete(Integer
					.valueOf(objekt.getMjesto().getIdMjesta()), currDate);
			if (pm == null) {
				pm = new Posjet();
				pm.setMjesto(mjestoDAO.find(Integer.valueOf(objekt.getMjesto()
						.getIdMjesta())));
				pm.setDatumPosjete(new Date(currDate.getTime()));
			}

			pm.setBrojPosjeta(pm.getBrojPosjeta() + 1);
			posjetDAO.merge(pm);

			if (objekt.getMjesto().getOtok() != null) {
				Posjet pot = posjetDAO.findByOtokDatumPosjete(Integer
						.valueOf(objekt.getMjesto().getOtok().getIdOtoka()),
						currDate);
				if (pot == null) {
					pot = new Posjet();
					pot.setOtok(otokDAO.find(Integer.valueOf(objekt.getMjesto()
							.getOtok().getIdOtoka())));
					pot.setDatumPosjete(new Date(currDate.getTime()));
				}

				pot.setBrojPosjeta(pot.getBrojPosjeta() + 1);
				posjetDAO.merge(pot);
			}
		}
	}

	public boolean isFavorit() {
		if (korisnik == null) {
			return false;
		}
		return objektDAO.findByIdObjektaIdMotritelja(idObjekta, korisnik
				.getIdKorisnika()) == null ? false : true;
	}

	@Transactional
	@Restrict("#{identity.loggedIn}")
	public void addToFavorites() {
		final Objekt objekt = objektDAO.find(idObjekta);
		objekt.getMotriteljs().add(korisnik);
		objektDAO.merge(objekt);
	}

	@Transactional
	public void removeFromFavorites() {
		// korisnik = korisnikDAO.merge(korisnik);
		final Objekt objekt = objektDAO.find(idObjekta);
		objekt.getMotriteljs().remove(korisnik);
		// korisnik.getFavoriti().remove(objekt);
		objektDAO.merge(objekt);
	}

}